package typistcal.commandlogic;

import java.util.InputMismatchException;

import typistcal.userinterface.UserInterface;

//@author A0105620X
public class Command {
	private String commandRecord;
	public String userInput;
	public CommandType commandType;
	public Event event;
	public String eventRecordAndFiles;

	public Command(String userInput) {
		commandRecord = userInput;
		this.userInput = userInput;
		decomposeCommand();
	}

	public Command() {}
	
	public String getCommandRecord(){
		return commandRecord;
	}

	private void decomposeCommand() {
		
		try {
			userInput = findCommandType().trim();
			if (userInput.isEmpty() && commandType != CommandType.SHOW_INFO) {
				userInput = UserInterface
						.displayAndAskForFeedback("Please enter your task/keyword");
				commandRecord = commandRecord.concat(userInput);
			}
			findParametersNeeded();
		} catch (Exception e) {
			commandType = CommandType.INVALID;
		}
	}

	private String findCommandType() {
		try {
			commandType = CommandTypeKeyword.findCommandTypeKeyword(userInput);
		} catch (InputMismatchException e) {
			
			commandType = CommandType.ADD_INFO;
		}
		userInput = CommandTypeKeyword.remove(commandType, userInput);
		if(commandType == CommandType.FIND_INFO){
			commandType = CommandType.SHOW_INFO;
		}
		return userInput.trim();
	}

	private void findParametersNeeded() {
		event = new Event(userInput,commandType);
	}

	public boolean isUndoable() {
		switch (commandType) {
		case ADD_INFO:
		case ADD_FOR_REDO:
		case DELETE_INFO:
		case DELETE_FOR_REDO:
		case UPDATE_INFO:
		case UPDATE_FOR_REDO:
			return true;
		default:
			return false;
		}
	}

	public Command reverseCommandForUndo(String feedback) {
		Command reversedCommand = new Command();
		
		castCommandTypeToUndo(reversedCommand);
		reversedCommand.eventRecordAndFiles = removeMessageForUser(feedback, reversedCommand);
		return reversedCommand;
	}

	private void castCommandTypeToUndo(Command reversedCommand) {
		switch (commandType) {
		case ADD_INFO:
		case ADD_FOR_REDO:
			reversedCommand.commandType = CommandType.DELETE_FOR_UNDO;
			break;
		case DELETE_INFO:
		case DELETE_FOR_REDO:
			reversedCommand.commandType = CommandType.ADD_FOR_UNDO;
			break;
		case UPDATE_INFO:
		case UPDATE_FOR_REDO:
			reversedCommand.commandType = CommandType.UPDATE_FOR_UNDO;
			break;
		default:
		}
	}

	private String removeMessageForUser(String feedback, Command reversedCommand) {
		switch (commandType) {
		case ADD_FOR_REDO:
		case ADD_FOR_UNDO:
		case ADD_INFO:
			feedback = feedback.replaceAll("is successfully added|are successfully added", "").trim();
			break;
		case DELETE_INFO:
		case DELETE_FOR_REDO:
		case DELETE_FOR_UNDO:
			feedback = feedback.replaceAll("is successfully deleted|are successfully deleted", "").trim();
			break;
		case UPDATE_FOR_UNDO:
		case UPDATE_FOR_REDO:
		case UPDATE_INFO:
			feedback = feedback.replaceAll("(?i)successfully", "").trim();
			break;
		default:
		}
		return feedback.substring(1).trim();
	}

	public boolean isUndo() {
		switch(commandType){
		case ADD_FOR_UNDO: case DELETE_FOR_UNDO: case UPDATE_FOR_UNDO:
			return true;
		default:
			return false;
		}
	}

	public Command reverseCommandForRedo(String feedback) {
		Command reversedCommand = new Command();
		
		castCommandTypeToRedo(reversedCommand);
		reversedCommand.eventRecordAndFiles = removeMessageForUser(feedback, reversedCommand);
		
		return reversedCommand;
	}

	private void castCommandTypeToRedo(Command reversedCommand) {
		switch (commandType) {
		case ADD_FOR_UNDO:
			reversedCommand.commandType = CommandType.DELETE_FOR_REDO;
			break;
		case DELETE_FOR_UNDO:
			reversedCommand.commandType = CommandType.ADD_FOR_REDO;
			break;
		case UPDATE_FOR_UNDO:
			reversedCommand.commandType = CommandType.UPDATE_FOR_REDO;
			break;
		default:
		}
	}

	public boolean isRedo() {
		switch(commandType){
		case ADD_FOR_REDO: case DELETE_FOR_REDO: case UPDATE_FOR_REDO:
			return true;
		default:
			return false;
		}
	}
}
